package com.emeraldparser.util;

import java.util.AbstractSet;
import java.util.Collection;
import java.util.Iterator;
import java.util.Set;

import com.google.common.base.Predicates;
import com.google.common.collect.AbstractIterator;
import com.google.common.collect.Iterables;
import com.google.common.collect.Iterators;
import com.google.common.collect.Sets;

public abstract class CollectionBasedSet<E> extends AbstractSet<E> {

	protected abstract Collection<E> collection();

	@Override
	public Iterator<E> iterator() {
		final Iterator<E> delegate = collection().iterator();
		final Set<E> seenElements = Sets.newHashSet();
		
		return new AbstractIterator<E>() {
			@Override
			protected E computeNext() {
				while (delegate.hasNext()) {
					E nextElement = delegate.next();
					if (seenElements.add(nextElement)) {
						return nextElement;
					}
				}
				
				return endOfData();
			}
		};
	}

	@Override
	public void clear() {
		collection().clear();
	}

	@Override
	public boolean removeAll(Collection<?> c) {
		return Iterables.removeAll(collection(), c);
	}

	@Override
	public boolean remove(Object o) {
		return Iterables.removeIf(collection(), Predicates.equalTo(o));
	}

	@Override
	public boolean retainAll(Collection<?> c) {
		return Iterables.retainAll(collection(), c);
	}

	@Override
	public int size() {
		return Iterators.size(iterator());
	}

}
